﻿#include "tcpclient.h"
#include "common_log.h"
#include <QEventLoop>
#include <QTimer>

TCPClient::TCPClient(QObject *parent)
	: QObject(parent)
{
	connect(&m_socket, &QTcpSocket::connected, this, &TCPClient::OnConnected);
	connect(&m_socket, &QTcpSocket::readyRead, this, &TCPClient::OnReadyRead);
	connect(&m_socket, &QTcpSocket::disconnected, this, &TCPClient::OnDisconnected);
	connect(&m_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::errorOccurred),
		this, &TCPClient::OnError);
}

TCPClient::~TCPClient()
{
}
bool TCPClient::ConnectToHost(const QString& host, const unsigned int port)
{
	m_ip = host;
	m_port = port;
	m_socket.connectToHost(host, port);

	return m_socket.state() == QTcpSocket::ConnectingState;
}

bool TCPClient::SendMessage(const QByteArray& data) 
{
	if (m_socket.state() != QTcpSocket::ConnectingState) {
		log_error("socket has not connected");
		return false;
	}

	m_socket.write(data);

	return true;
}
bool TCPClient::SendMessageAndWaitAns(const QByteArray& data, QByteArray& ans, int timeoutMS)
{
	if (m_socket.state() != QTcpSocket::ConnectingState) {
		log_error("socket has not connected");
		ans = "TCP连接未建立";
		return false;
	}
	QEventLoop loop;
	QTimer timer;

	QEventLoop loop;
	QTimer timer;
	QByteArray response;

	// 设置超时
	timer.setSingleShot(true);
	connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);

	// 接收响应
	connect(this, &TCPClient::ResponseReceieved, &loop, [&](const QByteArray& data) {
		response = data;
		loop.quit();
		});

	// 发送请求
	m_socket.write(data);
	m_socket.flush();

	// 启动等待
	timer.start(timeoutMS);
	loop.exec();

	if (!timer.isActive()) {
		log_error("Wait for response timed out");
		ans = "等待恢复超时";
		return false;
	}
	ans = response;
	return true;
}

void TCPClient::OnDisconnected()
{
	log_error("IP:{}port:{} tcp socket disconnected", m_ip, m_port);
	emit TcpDisconnected();
}
void TCPClient::OnConnected()
{
	log_info("IP:{}port:{} tcp socket has connected", m_ip, m_port);
}

void TCPClient::OnReadyRead()
{
	QByteArray data = m_socket.readAll();
	emit ResponseReceieved(data);
	log_trace("IP:{}port:{} read data {}", m_ip, m_port, data);
}

void TCPClient::OnError(QAbstractSocket::SocketError error)
{
	log_info("IP:{}port:{} tcp socket has error {}", m_ip, m_port, (int)error);
	emit TcpErrored(error);
}
